package ascii

import (
	"image"
	"image/color"
	_ "image/jpeg" //如果要解析jpg,jpeg格式的图片, 必须引入这个包
	_ "image/png"  //如果要解析png格式的图片, 必须引入这个包
	"os"
	"strings"
)

func Pic2Ascii(imageFilePath string) string {
	f, _ := os.Open(imageFilePath) //打开
	img, _, _ := image.Decode(f)
	width := img.Bounds().Dx()
	height := img.Bounds().Dy()

	//缩放比例
	xScale := width / 150
	yScale := height / 50

	var sb strings.Builder

	for y := 0; y < height; y += yScale {
		for x := 0; x < width; x += xScale {
			c := pixcelToChar(img.At(x, y))
			sb.WriteRune(c)
		}
		sb.WriteString("\n")
	}
	return sb.String()
}

var BaseChars []rune

func init() {
	//左边最暗, 右边最亮 ▇■◆ 这几个字符效果反而不怎好
	BaseChars = []rune("@#$%&*^+=!~- ")
}

//RGB 转为灰度值的心理学公式 Gray = 0.30R + 0.59G + 0.11B 是怎么来的？ - 赵雪冰的回答 - 知乎
//https://www.zhihu.com/question/22039410/answer/24055217
//https://en.wikipedia.org/wiki/Grayscale
//根据rgb, 转成黑白图片的灰度
func pixcelToChar(color color.Color) rune {
	//红; 转换成 0 ~ 255 展示
	//绿; 转换成 0 ~ 255 展示
	//蓝; 转换成 0 ~ 255 展示
	//透明度, 转换成 0 ~ 255 展示; 0为完全透明; 255为完全不透明
	r, g, b, _ := color.RGBA()
	gray := uint16(0.299*float64(r>>8) + 0.578*float64(g>>8) + 0.114*float64(b>>8)) //灰度

	grayScale := float64(float64(gray) / float64(255)) // 0.0~1.0 的小数
	lightDegree := grayScale * float64(len(BaseChars))
	index := int(lightDegree + 0.5) //四舍五入; +0.5后向下取整
	var c rune
	if index >= len(BaseChars) {
		c = BaseChars[len(BaseChars)-1]
	} else {
		c = BaseChars[index]
	}
	return c
}
